Opened 16 months ago

Closed 12 months ago

Last modified 12 months ago

#8641 closed bug (fixed)

ghc with -odir and -prof (or any stub file) does not create the specified output directory

Reported by: wmarshall Owned by: ezyang
Priority: normal Milestone: 7.8.3
Component: Compiler Version: 7.9
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Compile-time crash Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

Calling ghc with -odir set to a non-existent directory causes ghc to create the directory. However, if the -prof option is also specified, ghc fails to create the directory and quits with an error.

Steps to reproduce:

$ echo 'main = print "Hello world"' > Main.hs

$ ghc Main.hs -odir bin
[1 of 1] Compiling Main             ( Main.hs, bin\Main.o )
Linking Main.exe ...

$ rm -Rvf bin
removed `bin/Main.o'
removed directory: `bin'

$ ghc Main.hs -odir bin -prof
[1 of 1] Compiling Main             ( Main.hs, bin\Main.o )
C:/Program Files (x86)/Haskell Platform/2013.2.0.0/mingw/bin/ld.exe: cannot open output file bin\Main.o: No such file or directory
collect2: ld returned 1 exit status

Expected result: The output directory is created regardless of whether -prof is specified.

The above commands were executed from within Cygwin, but the error occurs in the Windows command shell as well. (I used Cygwin here because it is easier to give precise instructions to reproduce the error.)

I have only tested this on Windows. I do not know if the issue exists on Linux or other platforms.

Change History (8)

comment:1 Changed 16 months ago by wmarshall

  • Summary changed from ghc with -odir and -prof cannot create the specified output directory to ghc with -odir and -prof does not create the specified output directory

comment:2 Changed 13 months ago by ezyang

  • Owner set to ezyang
  • Summary changed from ghc with -odir and -prof does not create the specified output directory to ghc with -odir and -prof (or any stub file) does not create the specified output directory
  • Version changed from 7.6.3 to 7.9

Applies to Linux too. The actual source of the problem is when compilation of the file involves a stub file (so foreign exports will trigger this too); we've forgotten to call createDirectoryIfMissing in DriverPipeline.hs. Should be easy to fix but I need to cook up a test-case...

Last edited 13 months ago by ezyang (previous) (diff)

comment:3 Changed 13 months ago by ezyang

Proposed patch:

diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
index 2c71967..93edf05 100644
--- a/compiler/main/DriverPipeline.hs
+++ b/compiler/main/DriverPipeline.hs
@@ -1261,6 +1261,10 @@ runPhase (RealPhase SplitAs) _input_fn dflags
 
         liftIO $ createDirectoryIfMissing True split_odir
 
+        -- we create directories for the object file, because it
+        -- might be a hierarchical module.
+        liftIO $ createDirectoryIfMissing True (takeDirectory output_fn)
+
         -- remove M_split/ *.o, because we're going to archive M_split/ *.o
         -- later and we don't want to pick up any old objects.
         fs <- liftIO $ getDirectoryContents split_odir

Nope, this isn't right.

Last edited 13 months ago by ezyang (previous) (diff)

comment:4 Changed 13 months ago by ezyang

From c7498bbdaa74dadd976c75c4e303c2050aa78277 Mon Sep 17 00:00:00 2001
From: "Edward Z. Yang" <[email protected]>
Date: Thu, 10 Apr 2014 18:28:11 -0700
Subject: [PATCH] Fix #8641, creating directories when we have stubs.

Signed-off-by: Edward Z. Yang <[email protected]>
---
 compiler/main/DriverPipeline.hs      | 2 ++
 testsuite/tests/driver/B042stub/C.hs | 6 ++++++
 testsuite/tests/driver/Makefile      | 8 ++++++++
 testsuite/tests/driver/all.T         | 5 +++++
 4 files changed, 21 insertions(+)
 create mode 100644 testsuite/tests/driver/B042stub/C.hs

diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs
index 2c71967..2816c94 100644
--- a/compiler/main/DriverPipeline.hs
+++ b/compiler/main/DriverPipeline.hs
@@ -1259,6 +1259,7 @@ runPhase (RealPhase SplitAs) _input_fn dflags
             osuf = objectSuf dflags
             split_odir  = base_o ++ "_" ++ osuf ++ "_split"
 
+        -- this also creates the hierarchy
         liftIO $ createDirectoryIfMissing True split_odir
 
         -- remove M_split/ *.o, because we're going to archive M_split/ *.o
@@ -1469,6 +1470,7 @@ runPhase (RealPhase MergeStub) input_fn dflags
  = do
      PipeState{maybe_stub_o} <- getPipeState
      output_fn <- phaseOutputFilename StopLn
+     liftIO $ createDirectoryIfMissing True (takeDirectory output_fn)
      case maybe_stub_o of
        Nothing ->
          panic "runPhase(MergeStub): no stub"
diff --git a/testsuite/tests/driver/B042stub/C.hs b/testsuite/tests/driver/B042stub/C.hs
new file mode 100644
index 0000000..73f069c
--- /dev/null
+++ b/testsuite/tests/driver/B042stub/C.hs
@@ -0,0 +1,6 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+module B042stub.C where
+
+foreign export ccall foo :: IO ()
+foo :: IO ()
+foo = return ()
diff --git a/testsuite/tests/driver/Makefile b/testsuite/tests/driver/Makefile
index 7673713..3603bb6 100644
--- a/testsuite/tests/driver/Makefile
+++ b/testsuite/tests/driver/Makefile
@@ -222,6 +222,14 @@ test042:
 	"$(TEST_HC)" $(TEST_HC_OPTS_NO_RECOMP) -v0 --make B042/C.hs -odir obj042
 	test -f obj042/B042/C$(OBJSUFFIX)
 
+# test -odir with stubs
+test042stub:
+	$(RM) -rf obj042stub
+	mkdir obj042stub
+	$(RM) B042stub/C.hi
+	"$(TEST_HC)" $(TEST_HC_OPTS_NO_RECOMP) -v0 --make B042stub/C.hs -odir obj042stub
+	test -f obj042stub/B042stub/C$(OBJSUFFIX)
+
 # test -hidir
 test043:
 	$(RM) -f B043/C$(OBJSUFFIX)
diff --git a/testsuite/tests/driver/all.T b/testsuite/tests/driver/all.T
index aa4bc9b..ed0ce0f 100644
--- a/testsuite/tests/driver/all.T
+++ b/testsuite/tests/driver/all.T
@@ -142,6 +142,11 @@ test('driver042',
      run_command,
      ['$MAKE -s --no-print-directory test042'])
 
+test('driver042stub',
+     extra_clean(['B042stub/C.hi', 'obj042stub/B042stub/C.o', 'obj042stub/B042stub/', 'obj042stub/']),
+     run_command,
+     ['$MAKE -s --no-print-directory test042stub'])
+
 test('driver043',
      extra_clean(['B043/C.hi', 'B043/C.o',
                   'hi043/B043/C.hi', 'hi043/B043', 'hi043']),
-- 
1.8.3.2


comment:5 Changed 13 months ago by Edward Z. Yang <ezyang@…>

In c7498bbdaa74dadd976c75c4e303c2050aa78277/ghc:

Fix #8641, creating directories when we have stubs.

Signed-off-by: Edward Z. Yang <[email protected]>

comment:6 Changed 13 months ago by ezyang

  • Status changed from new to merge

comment:7 Changed 12 months ago by thoughtpolice

  • Resolution set to fixed
  • Status changed from merge to closed

Merged in 7.8, thanks!

comment:8 Changed 12 months ago by thoughtpolice

  • Milestone set to 7.8.3
Note: See TracTickets for help on using tickets.