@@ -37,66 +37,132 @@ import System.Process
38-----------------------------------------------------------------------
38-----------------------------------------------------------------------
39-- Main function
39-- Main function
41codegenJava :: [(Name, SExp)] -> -- initialization of globals
40codegenJava :: [(Name, SExp)] -> -- initialization of globals
42− [(Name, SDecl)] ->
41+ [(Name, SDecl)] -> -- decls
43 FilePath -> -- output file name
42 FilePath -> -- output file name
44 [String] -> -- headers
43 [String] -> -- headers
45 [String] -> -- libs
44 [String] -> -- libs
46 OutputType ->
45 OutputType ->
48−codegenJava globalInit defs out hdrs libs exec = do
47+codegenJava globalInit defs out hdrs libs exec =
48+ withTgtDir exec out (codegenJava' exec)
50+ codegenJava' :: OutputType -> FilePath -> IO ()
51+ codegenJava' Raw tgtDir = do
52+ srcDir <- prepareSrcDir exec tgtDir
53+ generateJavaFile globalInit defs hdrs srcDir out
54+ codegenJava' MavenProject tgtDir = do
55+ codegenJava' Raw tgtDir
56+ generatePom tgtDir out libs
57+ codegenJava' Object tgtDir = do
58+ codegenJava' MavenProject tgtDir
59+ invokeMvn tgtDir "compile"
60+ copyClassFiles tgtDir out
62+ codegenJava' _ tgtDir = do
63+ codegenJava' MavenProject tgtDir
64+ invokeMvn tgtDir "package";
66+ makeJarExecutable out
69+-----------------------------------------------------------------------
72+withTgtDir :: OutputType -> FilePath -> (FilePath -> IO ()) -> IO ()
73+withTgtDir Raw out action = action (dropFileName out)
74+withTgtDir MavenProject out action = createDirectoryIfMissing False out >> action out
49− withTempdir (takeBaseName out) $ \ tmpDir -> do
75+withTgtDir _ out action = withTempdir (takeBaseName out) action
77+prepareSrcDir :: OutputType -> FilePath -> IO FilePath
78+prepareSrcDir Raw tgtDir = return tgtDir
79+prepareSrcDir _ tgtDir = do
50− let srcdir = tmpDir </> "src" </> "main" </> "java"
80+ let srcDir = (tgtDir </> "src" </> "main" </> "java")
51− createDirectoryIfMissing True srcdir
81+ createDirectoryIfMissing True srcDir
52− let (Ident clsName) = either error id (mkClassName out)
82+ return srcDir
53− let outjava = srcdir </> clsName <.> "java"
83+
84+javaFileName :: FilePath -> FilePath -> FilePath
85+javaFileName srcDir out =
86+ either error (\ (Ident clsName) -> srcDir </> clsName <.> "java") (mkClassName out)
88+generateJavaFile :: [(Name, SExp)] -> -- initialization of globals
89+ [(Name, SDecl)] -> -- definitions
90+ [String] -> -- headers
91+ FilePath -> -- Source dir
92+ FilePath -> -- output target
94+generateJavaFile globalInit defs hdrs srcDir out = do
54− let jout = either error
95+ let code = either error
55 (prettyPrint)-- flatIndent . prettyPrint)
96 (prettyPrint)-- flatIndent . prettyPrint)
56 (evalStateT (mkCompilationUnit globalInit defs hdrs out) mkCodeGenEnv)
97 (evalStateT (mkCompilationUnit globalInit defs hdrs out) mkCodeGenEnv)
57− writeFile outjava jout
98+ writeFile (javaFileName srcDir out) code
59− then copyFile outjava (takeDirectory out </> clsName <.> "java")
100+pomFileName :: FilePath -> FilePath
60− else do
101+pomFileName tgtDir = tgtDir </> "pom.xml"
103+generatePom :: FilePath -> -- tgt dir
104+ FilePath -> -- output target
107+generatePom tgtDir out libs = do
61− execPom <- getExecutablePom
108+ execPom <- getExecutablePom
62− execPomTemplate <- TIO.readFile execPom
109+ execPomTemplate <- TIO.readFile execPom
110+ let (Ident clsName) = either error id (mkClassName out)
63− let execPom = T.replace (T.pack "$MAIN-CLASS$")
111+ let execPom = T.replace (T.pack "$MAIN-CLASS$")
64− (T.pack clsName)
112+ (T.pack clsName)
65− (T.replace (T.pack "$ARTIFACT-NAME$")
113+ (T.replace (T.pack "$ARTIFACT-NAME$")
66− (T.pack $ takeBaseName out)
114+ (T.pack $ takeBaseName out)
67− (T.replace (T.pack "$DEPENDENCIES$")
115+ (T.replace (T.pack "$DEPENDENCIES$")
68− (mkPomDependencies libs)
116+ (mkPomDependencies libs)
69− execPomTemplate
117+ execPomTemplate
72− TIO.writeFile (tmpDir </> "pom.xml") execPom
120+ TIO.writeFile (pomFileName tgtDir) execPom
122+invokeMvn :: FilePath -> String -> IO ()
123+invokeMvn tgtDir command = do
73− mvnCmd <- getMvn
124+ mvnCmd <- getMvn
74− let args = ["-f", (tmpDir </> "pom.xml")]
125+ let args = ["-f", pomFileName tgtDir]
75− (exit, mvout, err) <- readProcessWithExitCode mvnCmd (args ++ ["compile"]) ""
126+ (exit, mvout, err) <- readProcessWithExitCode mvnCmd (args ++ [command]) ""
127+ when (exit /= ExitSuccess) $
76− when (exit /= ExitSuccess) $ error ("FAILURE: " ++ mvnCmd ++ " compile\n" ++ err ++ mvout)
128+ error ("FAILURE: " ++ mvnCmd ++ " " ++ command ++ "\n" ++ err ++ mvout)
77− if (exec == Object)
129+
78− then do
130+classFileDir :: FilePath -> FilePath
79− classFiles <-
131+classFileDir tgtDir = tgtDir </> "target" </> "classes"
133+copyClassFiles :: FilePath -> FilePath -> IO ()
134+copyClassFiles tgtDir out = do
80− map (\ clsFile -> tmpDir </> "target" </> "classes" </> clsFile)
135+ classFiles <- map (\ clsFile -> classFileDir tgtDir </> clsFile)
81 . filter ((".class" ==) . takeExtension)
136 . filter ((".class" ==) . takeExtension)
82− <$> getDirectoryContents (tmpDir </> "target" </> "classes")
137+ <$> getDirectoryContents (classFileDir tgtDir)
83− mapM_ (\ clsFile -> copyFile clsFile (takeDirectory out </> takeFileName clsFile))
138+ mapM_ (\ clsFile -> copyFile clsFile (takeDirectory out </> takeFileName clsFile)) classFiles
85− else do
140+jarFileName :: FilePath -> FilePath -> FilePath
86− (exit, mvout, err) <- readProcessWithExitCode mvnCmd (args ++ ["package"]) ""
87− when (exit /= ExitSuccess) (error ("FAILURE: " ++ mvnCmd ++ " package\n" ++ err ++ mvout))
88− copyFile (tmpDir </> "target" </> (takeBaseName out) <.> "jar") out
141+jarFileName tgtDir out = tgtDir </> "target" </> (takeBaseName out) <.> "jar"
143+copyJar :: FilePath -> FilePath -> IO ()
145+ copyFile (jarFileName tgtDir out) out
147+makeJarExecutable :: FilePath -> IO ()
148+makeJarExecutable out = do
89− handle <- openBinaryFile out ReadMode
149+ handle <- openBinaryFile out ReadMode
90− contents <- TIO.hGetContents handle
150+ contents <- TIO.hGetContents handle
91− hClose handle
151+ hClose handle
92− handle <- openBinaryFile out WriteMode
152+ handle <- openBinaryFile out WriteMode
93− TIO.hPutStr handle (T.append (T.pack jarHeader) contents)
153+ TIO.hPutStr handle (T.append (T.pack jarHeader) contents)
94− hFlush handle
154+ hFlush handle
95− hClose handle
155+ hClose handle
96− perms <- getPermissions out
156+ perms <- getPermissions out
97− setPermissions out (setOwnerExecutable True perms)
157+ setPermissions out (setOwnerExecutable True perms)
98− readProcess mvnCmd (args ++ ["clean"]) ""
158+
99− removeFile (tmpDir </> "pom.xml")
159+removePom :: FilePath -> IO ()
160+removePom tgtDir = removeFile (pomFileName tgtDir)
162+cleanUpTmp :: FilePath -> IO ()
163+cleanUpTmp tgtDir = do
164+ invokeMvn tgtDir "clean"
101-----------------------------------------------------------------------
167-----------------------------------------------------------------------
102-- Jar and Pom infrastructure
168-- Jar and Pom infrastructure