Author Topic: Directory separator in project file (.cbp)  (Read 33020 times)

rblenis

  • Guest
Directory separator in project file (.cbp)
« 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.

Offline Hadomunt

  • Multiple posting newcomer
  • *
  • Posts: 11
Re: Directory separator in project file (.cbp)
« Reply #1 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.)

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: Directory separator in project file (.cbp)
« Reply #2 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)


Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #3 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:
  • include directories are not converted
  • commands are not converted (that's a tricky part, as e.g. zip -jq9 devel/share/CodeBlocks/resources.zip *.png won't work on some zip distros on Windows)
  • command line parameters are not converted, tricky, too
  • external deps are not converted
  • UNC names / path's are not handled correctly
  • Why didn't you use the existing UnixFilename method? NativeToUnix won'T work with macros IMHO, and macros should be considered for path's.

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. :-\ :(
« Last Edit: July 19, 2012, 08:34:05 am by MortenMacFly »
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #4 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("/")))
                 ;
        }
    }
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #5 on: July 19, 2012, 08:54:17 am »
...here comes an alternative patch accordingly.

Edit: Patch updated (see more recent post).
« Last Edit: August 07, 2012, 08:27:56 pm by MortenMacFly »
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline Hadomunt

  • Multiple posting newcomer
  • *
  • Posts: 11
Re: Directory separator in project file (.cbp)
« Reply #6 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?)

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #7 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. ???
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Directory separator in project file (.cbp)
« Reply #8 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.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #9 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.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #10 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. ::)
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: Directory separator in project file (.cbp)
« Reply #11 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.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9694
Re: Directory separator in project file (.cbp)
« Reply #12 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.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13413
    • Travis build status
Re: Directory separator in project file (.cbp)
« Reply #13 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...
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: Directory separator in project file (.cbp)
« Reply #14 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, 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...)