Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => Topic started by: rblenis on July 15, 2012, 04:40:01 am

Title: Directory separator in project file (.cbp)
Post by: rblenis on July 15, 2012, 04:40:01 am
I have devs using windows and linux builds of CodeBlocks, and each version keeps flipping the directory separator ('/' vs '\'), making it a pain to see what the is actually changed in the project when viewing diffs. Is there a way to make CodeBlocks stop changing it, or make both versions always use the same (I prefer linux '/'). I could look at doing it myself, but wanted to make sure I had not overlooked a configuration option, and would not want to invest time in adding/modifying code if others thought this was not useful or it would cause other problems that I'm not thinking about.
Title: Re: Directory separator in project file (.cbp)
Post by: Hadomunt on July 15, 2012, 07:29:31 pm
Code BLocks is not changing this but the operating systems are.
Maybe it would be a good idea to standardize on directory separator and newline symbols in code blocks files.
Since Code::Blocks itself is cross platform it seems very practical to make file descriptions also cross platform.
Using '/' (also my preference) for directory separator and /r/n for a new line.  (There is a technical reason to use this and not /n, but I forgot what that was.)
Title: Re: Directory separator in project file (.cbp)
Post by: Alpha on July 16, 2012, 04:05:41 am
Try this patch:
Code
Index: src/sdk/globals.cpp
===================================================================
--- src/sdk/globals.cpp (revision 8133)
+++ src/sdk/globals.cpp (working copy)
@@ -201,6 +201,11 @@
 
     return result;
 }
+wxString NativeToUnix(const wxString& filename)
+{
+    wxFileName fname(filename);
+    return fname.GetFullPath(wxPATH_UNIX);
+}
 
 void QuoteStringIfNeeded(wxString& str)
 {
Index: src/sdk/projectloader.cpp
===================================================================
--- src/sdk/projectloader.cpp (revision 8133)
+++ src/sdk/projectloader.cpp (working copy)
@@ -1175,7 +1175,7 @@
             {
                 wxFileName fname(outputFileName);
                 fname.ClearExt();
-                outputFileName = fname.GetFullPath();
+                outputFileName = fname.GetFullPath(wxPATH_UNIX);
             }
 
             if (   (prefixPolicy == tgfpPlatformDefault)
@@ -1197,7 +1197,7 @@
                         if (!outputFileNameWOPrefix.IsEmpty())
                         {
                             fname.SetFullName(outputFileNameWOPrefix);
-                            outputFileName = fname.GetFullPath();
+                            outputFileName = fname.GetFullPath(wxPATH_UNIX);
                         }
                     }
                 }
@@ -1207,19 +1207,19 @@
             if (target->GetTargetType() == ttDynamicLib)
             {
                 if (target->GetDynamicLibImportFilename() != _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)"))
-                  outnode->SetAttribute("imp_lib",  cbU2C(target->GetDynamicLibImportFilename()));
+                  outnode->SetAttribute("imp_lib",  cbU2C(NativeToUnix(target->GetDynamicLibImportFilename())));
                 if (target->GetDynamicLibImportFilename() != _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)"))
-                  outnode->SetAttribute("def_file", cbU2C(target->GetDynamicLibDefFilename()));
+                  outnode->SetAttribute("def_file", cbU2C(NativeToUnix(target->GetDynamicLibDefFilename())));
             }
             outnode->SetAttribute("prefix_auto", prefixPolicy == tgfpPlatformDefault ? "1" : "0");
             outnode->SetAttribute("extension_auto", extensionPolicy == tgfpPlatformDefault ? "1" : "0");
 
             if (target->GetWorkingDir() != _T("."))
-                AddElement(tgtnode, "Option", "working_dir", target->GetWorkingDir());
+                AddElement(tgtnode, "Option", "working_dir", NativeToUnix(target->GetWorkingDir()));
             if (target->GetObjectOutput() != _T(".objs"))
-                AddElement(tgtnode, "Option", "object_output", target->GetObjectOutput());
+                AddElement(tgtnode, "Option", "object_output", NativeToUnix(target->GetObjectOutput()));
             if (target->GetDepsOutput() != _T(".deps"))
-                AddElement(tgtnode, "Option", "deps_output", target->GetDepsOutput());
+                AddElement(tgtnode, "Option", "deps_output", NativeToUnix(target->GetDepsOutput()));
         }
         if (!target->GetExternalDeps().IsEmpty())
             AddElement(tgtnode, "Option", "external_deps", target->GetExternalDeps());
@@ -1377,7 +1377,7 @@
         ProjectFile* f = pfa[i];
         FileType ft = FileTypeOf(f->relativeFilename);
 
-        TiXmlElement* unitnode = AddElement(prjnode, "Unit", "filename", f->relativeFilename);
+        TiXmlElement* unitnode = AddElement(prjnode, "Unit", "filename", NativeToUnix(f->relativeFilename));
         if (!f->compilerVar.IsEmpty())
         {
             wxString ext = f->relativeFilename.AfterLast(_T('.')).Lower();
@@ -1404,7 +1404,7 @@
             AddElement(unitnode, "Option", "weight", f->weight);
 
         if (!f->virtual_path.IsEmpty())
-            AddElement(unitnode, "Option", "virtualFolder", f->virtual_path);
+            AddElement(unitnode, "Option", "virtualFolder", NativeToUnix(f->virtual_path));
 
         // loop and save custom build commands
         for (pfCustomBuildMap::iterator it = f->customBuild.begin(); it != f->customBuild.end(); ++it)
Index: src/include/globals.h
===================================================================
--- src/include/globals.h (revision 8133)
+++ src/include/globals.h (working copy)
@@ -181,6 +181,7 @@
 extern DLLIMPORT void AppendArray(const wxArrayString& from, wxArrayString& to);
 
 extern DLLIMPORT wxString UnixFilename(const wxString& filename);
+extern DLLIMPORT wxString NativeToUnix(const wxString& filename);
 extern DLLIMPORT void QuoteStringIfNeeded(wxString& str);
 
 /// Escapes spaces and tabs (NOT quoting the string)

Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on July 19, 2012, 08:28:01 am
Try this patch:
This is a nice work, however, it is not that easy, and therefoe this patch is incomplete:

So in the end the user is responsible for doing some of these points, maybe, but nevertheless you still get two different project files if you save the same under Linux and Windows. :-\ :(
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on July 19, 2012, 08:39:31 am
...just an idea: Wouldn't it be enough to use generally use UnixFilename (including the places where you converted wxFileName to wxPATH_UNIX and used NativeToUnix), but then implement the Windows part in this method as following:
Code
    if (platform::windows)
    {
        bool unc_name = result.StartsWith(_T("\\\\"));

        while (result.Replace(_T("/"), _T("\\")))
            ;
        while (result.Replace(_T("\\\\"), _T("\\")))
            ;

        if (unc_name)
            result = _T("\\") + result;
        else // THIS PART IS NEW!!!
        {
             while (result.Replace(_T("\\"), _T("/")))
                 ;
        }
    }
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on July 19, 2012, 08:54:17 am
...here comes an alternative patch accordingly.

Edit: Patch updated (see more recent post).
Title: Re: Directory separator in project file (.cbp)
Post by: Hadomunt on July 27, 2012, 06:42:42 pm
Seems like most practical thing to do is to use:
- Relative paths as much as possible
- Automatically convert the directory separator.

We should have codeblocks checking on which platform it is in and use/change the separators accordingly.
With standardizing path description internally we could avoid things switching constantly I guess?
(Modifying them to correct representation when giving to other applications/command line?)
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on July 28, 2012, 03:13:32 pm
Seems like most practical thing to do is to use:
- Relative paths as much as possible
- Automatically convert the directory separator.
That's how it is now and what was complained. ::)

If that's OK we don't need to change anything. ???
Title: Re: Directory separator in project file (.cbp)
Post by: Jenna on July 28, 2012, 03:26:53 pm
Seems like most practical thing to do is to use:
- Relative paths as much as possible
- Automatically convert the directory separator.
That's how it is now and what was complained. ::)

If that's OK we don't need to change anything. ???

If I understand the post correctly the conversion should only be done if we call any external programs, like compiler, linker etc. , but internally (especially in project- and workspace-files) use the same syntax on all platforms.
This might probaly lead to problems with (windows-) parameters that get saved in the project-file, because they also use a slash in many (most?) cases.
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on July 28, 2012, 07:35:21 pm
If I understand the post correctly the conversion should only be done if we call any external programs, like compiler, linker etc. , but internally (especially in project- and workspace-files) use the same syntax on all platforms.
Ah, OK... ::)

This might probaly lead to problems with (windows-) parameters that get saved in the project-file, because they also use a slash in many (most?) cases.
That what my approach tries to avoid: I only change path's we can change safely w/o interfering with tools not supporting it (although I have to admit that I never tried to compile a file using MSVC with this patch applied). For Windows, you cannot easily convert all back-slashes to slashes. For this I see no way - just consider this command line:
mytool.exe /lflag C:\Foo\Bar \\server\baz /DDEF
How would you safely do the right thing here? Impossible.

The main request was out of the fact that if you saved a cross-platform project with Windows and then with Unix the files are different. With the patch presented here they wouldn't. I honestly think that's all we can do. Everything else is just too risky and would certainly work on the one hand, but break a feature on the other.
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 07, 2012, 06:51:43 am
...here comes an alternative patch accordingly.
For the record: Both patches have serious side-effects. The most serious one is that having these applied and using macros related to one of these path's on Windows will break the console commands, as e.g.
"copy myfoldel/fo/bar .." won't work on Windows. So either there is a context and platform sensitive way to convert the path correctly or it remains as it is.
As I don't see a way w/o much and error-prone effort for the first choice I'm afraid the second is the way to go. ::)
Title: Re: Directory separator in project file (.cbp)
Post by: Alpha on August 07, 2012, 03:39:33 pm
In my opinion, anything saved to a .cbp (or .workspace) that has an internal representation as a path or a file name should be saved with "/" and converted (in memory) to the native format on load.  (Attempting conversion of anything else - command line parameters, pre/post-build steps - would both be unwise and unlikely to work reliably.)
This would remain completely backwards compatible, and deal with enough cases to (mostly) take care of the original problem: sharing the same project file between Windows and Linux.

  • Why didn't you use the existing UnixFilename method?
(Very late reply :), but) I was reading/writing quickly and missed it.
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 07, 2012, 05:04:24 pm
In my opinion, anything saved to a .cbp (or .workspace) that has an internal representation as a path or a file name should be saved with "/" and converted (in memory) to the native format on load.
Well and that is the problem: You don't know, if pre- or post-build steps (for example) are a path or if a "\" or "/" is part of a macro etc.. So it is error-prone. There is no such easy thing like "convert on load" without making mistakes. Only the user knows how (s)he would like to interpret / setup such things. So its best to leave it as setup by the user IMHO.

BTW: And a partial solution makes no sense, too - because then you still have differences.
Title: Re: Directory separator in project file (.cbp)
Post by: oBFusCATed on August 07, 2012, 05:21:39 pm
BTW: And a partial solution makes no sense, too - because then you still have differences.
Yes, but they will be far less. And adding a file to the project won't cause conflicts.

For the macros aren't we saving them as the user have typed them? For example "$(MY_MACRO)/test" is save as is.

My opinion is that we must not modify anything the users has typed with the keyboard and we should modified anything entered by a paths-like dialog.
So the "other options" in the linker/compiler or the "post/pre build steps" won't be changed, they will be save as entered.
The paths in the search paths section of the settings will be save in unix/dos format (doesn't matter which, but I prefer unix of course:) ).
And if we want to preserve the cross platform support we can provide a marco to convert a path to native format, which can be used in the non-converted sections.
It will be a little tedious to setup, but it will be explicit and not work auto magically.

p.s. this is the second time I post similar answer, the first time the post gone missing for some strange reason...
Title: Re: Directory separator in project file (.cbp)
Post by: Alpha on August 07, 2012, 05:27:29 pm
Well and that is the problem: You don't know, if pre- or post-build steps (for example) are a path or if a "\" or "/" is part of a macro etc.. So it is error-prone.
(Attempting conversion of anything else - command line parameters, pre/post-build steps - would both be unwise and unlikely to work reliably.)
?!  I was only suggesting using this on variables that Code::Blocks already knows are guaranteed to only be paths or file names.  From Project file format (http://wiki.codeblocks.org/index.php?title=Project_file), the variables that are saved in:
Code
<Script file="" />
<Option output="default" prefix_auto="1" extension_auto="1" />
<Option working_dir="." />
<Option object_output=".objs" />
<Option deps_output=".deps" />
<Option external_deps="" />
<Option additional_output="" />
<Option host_application="" />
<Add directory="" />
<Unit filename="BuildScripts/config.script"></Unit>
<Option virtualFolder="" />
There is no such easy thing like "convert on load" without making mistakes.
For these specific cases (or most of them), Code::Blocks already uses a "convert on load" (this is how it accepts, for example, files with Linux paths on a Windows computer) - which is what caused the problem listed in the first post, it is not standardized which format they save back to.


(Oops, our posts crossed...)
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 07, 2012, 06:19:37 pm
For the macros aren't we saving them as the user have typed them? For example "$(MY_MACRO)/test" is save as is.
Huh? I doubt this is. If so, my attempt would be OK. I believe "$(MY_MACRO)/test" would be "$(MY_MACRO)\test" on Windows.

BTW: And a partial solution makes no sense, too - because then you still have differences.
Yes, but they will be far less. And adding a file to the project won't cause conflicts.
Why wouldn't it? If you add a file on Windows and save creates a different file when adding a file on Linux and save - that's what I experienced with C::B for decades now and that's what I wanted to fix.

?!  I was only suggesting using this on variables that Code::Blocks already knows are guaranteed to only be paths or file names.  From Project file format (http://wiki.codeblocks.org/index.php?title=Project_file), the variables that are saved in: [...]
I'm afraid this is not entirely true. For example, the output file and object_output can have macros.

Well - let me suggest another approach: Use my patch, modify it the way you think it is correct and re-send. I'll try with some of my projects that make heavy macros usage and report back. I could also think of at least one thing: Definitely the unit files cause most conflicts and diffs - so if its just for them as an interim-step I am fine.

Why I am so sceptic is that the errors I got were really frustrating, because for example copy operations based on macros that used the TARGET_OUTPUT_FILE macro (or alike) were suddenly no longer working causing strange effects with my projects because files were not updated as they should have been. This is exactly the side-effects I meant you don't think off in the first place. And btw: The error message was not highlighted, so it took me a while. :-(
Title: Re: Directory separator in project file (.cbp)
Post by: oBFusCATed on August 07, 2012, 06:51:11 pm
Huh? I doubt this is. If so, my attempt would be OK. I believe "$(MY_MACRO)/test" would be "$(MY_MACRO)\test" on Windows.
My thought was the we're not expanding the marcos before saving the file, so what are the problems if we always save them in unix format?
C::B already does the conversion if the file have been saved on unix, doesn't it?

Why wouldn't it? If you add a file on Windows and save creates a different file when adding a file on Linux and save - that's what I experienced with C::B for decades now and that's what I wanted to fix.
I think we misunderstand each other.
What I was telling is that the most conflicts happen in the files added to the project, so a partial solution will minimize the problem.
You have said it won't.
Title: Re: Directory separator in project file (.cbp)
Post by: Alpha on August 07, 2012, 07:57:11 pm
Well - let me suggest another approach: Use my patch, modify it the way you think it is correct and re-send. I'll try with some of my projects that make heavy macros usage and report back. I could also think of at least one thing: Definitely the unit files cause most conflicts and diffs - so if its just for them as an interim-step I am fine.
I will see what I can come up with.
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 07, 2012, 08:17:14 pm
I will see what I can come up with.
Forget it for a while and try the attached patch... this is my last attempt... ;D :P

Edit: Patch updated (see more recent post).
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 07, 2012, 08:19:25 pm
What I was telling is that the most conflicts happen in the files added to the project, so a partial solution will minimize the problem.
Yes, but whats the point in "minimising" here? Either it is the same (which would be nice!) or not. But if you are talking about SVN conflicts - I agree.
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 07, 2012, 08:27:02 pm
Forget it for a while and try the attached patch... this is my last attempt... ;D :P
...ooops: Tiny error in the patch - corrected version here:
Title: Re: Directory separator in project file (.cbp)
Post by: oBFusCATed on August 07, 2012, 11:02:10 pm
But if you are talking about SVN conflicts - I agree.
Yes, the whole problem is related to SVN/VCS conflicts, as the files are not meant to be edited by humans anyway and if VCS is not used the path separator won't be a problem.
Title: Re: Directory separator in project file (.cbp)
Post by: MortenMacFly on August 09, 2012, 11:34:52 am
...ooops: Tiny error in the patch - corrected version here:
BTW - with this patch I got another side-effect: CC does not work well anymore and mixes files. That's exactly what I am talking about with undesired side-effects.

However, I've fixed this in my local copy already. It was actually a bad interface in CC.
Title: Re: Directory separator in project file (.cbp)
Post by: Alpha on August 11, 2012, 05:05:49 am
Try this patch.
Title: Re: Directory separator in project file (.cbp)
Post by: oBFusCATed on August 24, 2014, 06:41:23 pm
Seem this is reported as bug, once again. See https://sourceforge.net/p/codeblocks/tickets/36/
Title: Re: Directory separator in project file (.cbp)
Post by: Jenna on August 24, 2014, 11:44:20 pm
This seems to affect only libraries whitch contain paths.
See my comment: https://sourceforge.net/p/codeblocks/tickets/36/#7e28
Title: Re: Directory separator in project file (.cbp)
Post by: Jenna on August 25, 2014, 09:34:02 am
Can you test this patch ?
Code
commit b0baeda27eb28cc1e4b9652b6f49b47d8d1e9d16
Author: Jens Lody <jens@codeblocks.org>
Date:   Mon Aug 25 09:31:09 2014 +0200

    * fix for bug #36 Path slashes in project file flip on save between windows and nix

Index: src/sdk/projectloader.cpp
===================================================================
--- src/sdk/projectloader.cpp
+++ src/sdk/projectloader.cpp
@@ -1404,7 +1404,7 @@

         node = AddElement(tgtnode, "Linker");
         AddArrayOfElements(node, "Add", "option",    target->GetLinkerOptions());
-        AddArrayOfElements(node, "Add", "library",   target->GetLinkLibs());
+        AddArrayOfElements(node, "Add", "library",   target->GetLinkLibs(), true);
         AddArrayOfElements(node, "Add", "directory", target->GetLibDirs(), true);
         if (node->NoChildren())
             tgtnode->RemoveChild(node);
@@ -1468,7 +1468,7 @@

     node = AddElement(prjnode, "Linker");
     AddArrayOfElements(node, "Add", "option",    m_pProject->GetLinkerOptions());
-    AddArrayOfElements(node, "Add", "library",   m_pProject->GetLinkLibs());
+    AddArrayOfElements(node, "Add", "library",   m_pProject->GetLinkLibs(), true);
     AddArrayOfElements(node, "Add", "directory", m_pProject->GetLibDirs(), true);
     if (node->NoChildren())
         prjnode->RemoveChild(node);
Title: Re: Directory separator in project file (.cbp)
Post by: Jenna on August 25, 2014, 12:21:30 pm
I tested it on linux and windows 7 with relative and absolute paths (including drive-letter on win) and decided to commit it in svn r9859 .
Title: Re: Directory separator in project file (.cbp)
Post by: oBFusCATed on August 25, 2014, 08:42:50 pm
Thanks...