Merge pull request #8 from legalese/GF_LIB_PATH

GF_LIB_PATH can now be path1:path2:path3, not just 1path
This commit is contained in:
John J. Camilleri
2018-07-22 14:48:44 +02:00
committed by GitHub
6 changed files with 74 additions and 38 deletions

View File

@@ -412,21 +412,33 @@ use on-line ``h -FLAG``.
===File paths=== ===File import search paths===
Colon-separated lists of directories searched in the Colon-separated list of directories searched in the
given order: given order:
``` ```
--# -path=.:../abstract:../common:prelude --# -path=.:../abstract:../common:prelude
``` ```
This can be (in order of growing preference), as This can be (in order of increasing priority), as
first line in the top file, as flag to ``gf`` first line in the file, as flag to ``gf``
when invoked, or as flag to the ``i`` command. when invoked, or as flag to the ``i`` command.
The prefix ``--#`` is used only in files. The prefix ``--#`` is used only in files.
If the environment variabls ``GF_LIB_PATH`` is defined, its GF attempts to satisfy an ``import`` command by searching for the
value is automatically prefixed to each directory to import filename in the above search paths, initially qualified
extend the original search path. relative to the current working directory. If the file is not found in
that initial expansion, the search paths are re-qualified relative to
the directories given in the ``GF_LIB_PATH`` environment variable. If
``GF_LIB_PATH`` is not defined, its default value is
``/usr/local/share/gf-3.9/lib`` (assuming you have GF version 3.9).
If your GF resource grammar libraries are installed somewhere else,
you will want to set ``GF_LIB_PATH`` to point there instead. In a
pinch, you can point to the ``GF/lib/src/`` folder in your clone of
the GF source code repository.
Developers of resource grammars may find it useful to define multiple
directories, colon-separated, in ``GF_LIB_PATH``.
===Alternative grammar formats=== ===Alternative grammar formats===

View File

@@ -3204,7 +3204,10 @@ in the top of <CODE>FILE.gf</CODE> causes the GF compiler, when invoked on <CODE
to search through the current directory (<CODE>.</CODE>) and the directories to search through the current directory (<CODE>.</CODE>) and the directories
<CODE>present</CODE>, <CODE>prelude</CODE>, and <CODE>/home/aarne/GF/tmp</CODE>, in this order. <CODE>present</CODE>, <CODE>prelude</CODE>, and <CODE>/home/aarne/GF/tmp</CODE>, in this order.
If a directory <CODE>DIR</CODE> is not found relative to the working directory, If a directory <CODE>DIR</CODE> is not found relative to the working directory,
also <CODE>$(GF_LIB_PATH)/DIR</CODE> is searched. <CODE>$(GF_LIB_PATH)/DIR</CODE> is searched. <CODE>$GF_LIB_PATH</CODE>
can be a colon-separated list of directories, in which case each directory
in the list contributes to the search path expansion.
</P> </P>
<A NAME="toc53"></A> <A NAME="toc53"></A>
<H2>Alternative grammar input formats</H2> <H2>Alternative grammar input formats</H2>

View File

@@ -14,7 +14,7 @@ import GF.Infra.UseIO(IOE,FullPath,liftIO,getLibraryDirectory,putIfVerb,
justModuleName,extendPathEnv,putStrE,putPointE) justModuleName,extendPathEnv,putStrE,putPointE)
import GF.Data.Operations(raise,(+++),err) import GF.Data.Operations(raise,(+++),err)
import Control.Monad(foldM,when,(<=<)) import Control.Monad(foldM,when,(<=<),filterM,liftM)
import GF.System.Directory(doesFileExist,getModificationTime) import GF.System.Directory(doesFileExist,getModificationTime)
import System.FilePath((</>),isRelative,dropFileName) import System.FilePath((</>),isRelative,dropFileName)
import qualified Data.Map as Map(empty,insert,elems) --lookup import qualified Data.Map as Map(empty,insert,elems) --lookup
@@ -78,10 +78,14 @@ compileModule opts1 env@(_,rfs) file =
do file <- getRealFile file do file <- getRealFile file
opts0 <- getOptionsFromFile file opts0 <- getOptionsFromFile file
let curr_dir = dropFileName file let curr_dir = dropFileName file
lib_dir <- getLibraryDirectory (addOptions opts0 opts1) lib_dirs <- getLibraryDirectory (addOptions opts0 opts1)
let opts = addOptions (fixRelativeLibPaths curr_dir lib_dir opts0) opts1 let opts = addOptions (fixRelativeLibPaths curr_dir lib_dirs opts0) opts1
-- putIfVerb opts $ "curr_dir:" +++ show curr_dir ----
-- putIfVerb opts $ "lib_dir:" +++ show lib_dirs ----
ps0 <- extendPathEnv opts ps0 <- extendPathEnv opts
let ps = nub (curr_dir : ps0) let ps = nub (curr_dir : ps0)
-- putIfVerb opts $ "options from file: " ++ show opts0
-- putIfVerb opts $ "augmented options: " ++ show opts
putIfVerb opts $ "module search path:" +++ show ps ---- putIfVerb opts $ "module search path:" +++ show ps ----
files <- getAllFiles opts ps rfs file files <- getAllFiles opts ps rfs file
putIfVerb opts $ "files to read:" +++ show files ---- putIfVerb opts $ "files to read:" +++ show files ----
@@ -94,13 +98,17 @@ compileModule opts1 env@(_,rfs) file =
if exists if exists
then return file then return file
else if isRelative file else if isRelative file
then do lib_dir <- getLibraryDirectory opts1 then do
let file1 = lib_dir </> file lib_dirs <- getLibraryDirectory opts1
exists <- doesFileExist file1 let candidates = [ lib_dir </> file | lib_dir <- lib_dirs ]
if exists putIfVerb opts1 (render ("looking for: " $$ nest 2 candidates))
then return file1 file1s <- filterM doesFileExist candidates
else raise (render ("None of these files exists:" $$ nest 2 (file $$ file1))) case length file1s of
else raise (render ("File" <+> file <+> "does not exist.")) 0 -> raise (render ("Unable to find: " $$ nest 2 candidates))
1 -> do return $ head file1s
_ -> do putIfVerb opts1 ("matched multiple candidates: " +++ show file1s)
return $ head file1s
else raise (render ("File" <+> file <+> "does not exist"))
compileOne' :: Options -> CompileEnv -> FullPath -> IOE CompileEnv compileOne' :: Options -> CompileEnv -> FullPath -> IOE CompileEnv
compileOne' opts env@(gr,_) = extendCompileEnv env <=< compileOne opts gr compileOne' opts env@(gr,_) = extendCompileEnv env <=< compileOne opts gr

View File

@@ -34,8 +34,11 @@ import qualified Data.ByteString.Lazy as BS
parallelBatchCompile jobs opts rootfiles0 = parallelBatchCompile jobs opts rootfiles0 =
do setJobs jobs do setJobs jobs
rootfiles <- mapM canonical rootfiles0 rootfiles <- mapM canonical rootfiles0
lib_dir <- canonical =<< getLibraryDirectory opts lib_dirs1 <- getLibraryDirectory opts
filepaths <- mapM (getPathFromFile lib_dir opts) rootfiles lib_dirs2 <- mapM canonical lib_dirs1
let lib_dir = head lib_dirs2
when (length lib_dirs2 >1) $ ePutStrLn ("GF_LIB_PATH defines more than one directory; using the first, " ++ show lib_dir)
filepaths <- mapM (getPathFromFile [lib_dir] opts) rootfiles
let groups = groupFiles lib_dir filepaths let groups = groupFiles lib_dir filepaths
n = length groups n = length groups
when (n>1) $ ePutStrLn "Grammar mixes present and alltenses, dividing modules into two groups" when (n>1) $ ePutStrLn "Grammar mixes present and alltenses, dividing modules into two groups"

View File

@@ -153,7 +153,7 @@ data Flags = Flags {
optLiteralCats :: Set Ident, optLiteralCats :: Set Ident,
optGFODir :: Maybe FilePath, optGFODir :: Maybe FilePath,
optOutputDir :: Maybe FilePath, optOutputDir :: Maybe FilePath,
optGFLibPath :: Maybe FilePath, optGFLibPath :: Maybe [FilePath],
optDocumentRoot :: Maybe FilePath, -- For --server mode optDocumentRoot :: Maybe FilePath, -- For --server mode
optRecomp :: Recomp, optRecomp :: Recomp,
optProbsFile :: Maybe FilePath, optProbsFile :: Maybe FilePath,
@@ -208,9 +208,10 @@ parseModuleOptions args = do
then return opts then return opts
else errors $ map ("Non-option among module options: " ++) nonopts else errors $ map ("Non-option among module options: " ++) nonopts
fixRelativeLibPaths curr_dir lib_dir (Options o) = Options (fixPathFlags . o) fixRelativeLibPaths curr_dir lib_dirs (Options o) = Options (fixPathFlags . o)
where where
fixPathFlags f@(Flags{optLibraryPath=path}) = f{optLibraryPath=concatMap (\dir -> [curr_dir </> dir, lib_dir </> dir]) path} fixPathFlags f@(Flags{optLibraryPath=path}) = f{optLibraryPath=concatMap (\dir -> [parent </> dir
| parent <- curr_dir : lib_dirs]) path}
-- Showing options -- Showing options
@@ -423,7 +424,7 @@ optDescr =
literalCat x = set $ \o -> o { optLiteralCats = foldr Set.insert (optLiteralCats o) ((map identS . splitBy (==',')) x) } literalCat x = set $ \o -> o { optLiteralCats = foldr Set.insert (optLiteralCats o) ((map identS . splitBy (==',')) x) }
lexicalCat x = set $ \o -> o { optLexicalCats = foldr Set.insert (optLexicalCats o) (splitBy (==',') x) } lexicalCat x = set $ \o -> o { optLexicalCats = foldr Set.insert (optLexicalCats o) (splitBy (==',') x) }
outDir x = set $ \o -> o { optOutputDir = Just x } outDir x = set $ \o -> o { optOutputDir = Just x }
gfLibPath x = set $ \o -> o { optGFLibPath = Just x } gfLibPath x = set $ \o -> o { optGFLibPath = Just $ splitInModuleSearchPath x }
gfDocuRoot x = set $ \o -> o { optDocumentRoot = Just x } gfDocuRoot x = set $ \o -> o { optDocumentRoot = Just x }
recomp x = set $ \o -> o { optRecomp = x } recomp x = set $ \o -> o { optRecomp = x }
probsFile x = set $ \o -> o { optProbsFile = Just x } probsFile x = set $ \o -> o { optProbsFile = Just x }

View File

@@ -38,6 +38,7 @@ import Control.Monad(when,liftM,foldM)
import Control.Monad.Trans(MonadIO(..)) import Control.Monad.Trans(MonadIO(..))
import Control.Monad.State(StateT,lift) import Control.Monad.State(StateT,lift)
import Control.Exception(evaluate) import Control.Exception(evaluate)
import Data.List (nub)
--putIfVerb :: MonadIO io => Options -> String -> io () --putIfVerb :: MonadIO io => Options -> String -> io ()
putIfVerb opts msg = when (verbAtLeast opts Verbose) $ putStrLnE msg putIfVerb opts msg = when (verbAtLeast opts Verbose) $ putStrLnE msg
@@ -51,28 +52,32 @@ type FullPath = String
gfLibraryPath = "GF_LIB_PATH" gfLibraryPath = "GF_LIB_PATH"
gfGrammarPathVar = "GF_GRAMMAR_PATH" gfGrammarPathVar = "GF_GRAMMAR_PATH"
getLibraryDirectory :: MonadIO io => Options -> io FilePath getLibraryDirectory :: MonadIO io => Options -> io [FilePath]
getLibraryDirectory opts = getLibraryDirectory opts =
case flag optGFLibPath opts of case flag optGFLibPath opts of
Just path -> return path Just path -> return path
Nothing -> liftIO $ catch (getEnv gfLibraryPath) Nothing -> liftM splitSearchPath $ liftIO (catch (getEnv gfLibraryPath)
(\ex -> fmap (</> "lib") getDataDir) (\ex -> fmap (</> "lib") getDataDir))
getGrammarPath :: MonadIO io => FilePath -> io [FilePath] getGrammarPath :: MonadIO io => [FilePath] -> io [FilePath]
getGrammarPath lib_dir = liftIO $ do getGrammarPath lib_dirs = liftIO $ do
catch (fmap splitSearchPath $ getEnv gfGrammarPathVar) catch (fmap splitSearchPath $ getEnv gfGrammarPathVar)
(\_ -> return [lib_dir </> "alltenses",lib_dir </> "prelude"]) -- e.g. GF_GRAMMAR_PATH (\_ -> return $ concat [[lib_dir </> "alltenses", lib_dir </> "prelude"]
| lib_dir <- lib_dirs ]) -- e.g. GF_GRAMMAR_PATH
-- | extends the search path with the -- | extends the search path with the
-- 'gfLibraryPath' and 'gfGrammarPathVar' -- 'gfLibraryPath' and 'gfGrammarPathVar'
-- environment variables. Returns only existing paths. -- environment variables. Returns only existing paths.
extendPathEnv :: MonadIO io => Options -> io [FilePath] extendPathEnv :: MonadIO io => Options -> io [FilePath]
extendPathEnv opts = liftIO $ do extendPathEnv opts = liftIO $ do
let opt_path = flag optLibraryPath opts -- e.g. paths given as options let opt_path = nub $ flag optLibraryPath opts -- e.g. paths given as options
lib_dir <- getLibraryDirectory opts -- e.g. GF_LIB_PATH lib_dirs <- getLibraryDirectory opts -- e.g. GF_LIB_PATH
grm_path <- getGrammarPath lib_dir -- e.g. GF_GRAMMAR_PATH grm_path <- getGrammarPath lib_dirs -- e.g. GF_GRAMMAR_PATH
let paths = opt_path ++ [lib_dir] ++ grm_path let paths = opt_path ++ lib_dirs ++ grm_path
ps <- liftM concat $ mapM allSubdirs paths when (verbAtLeast opts Verbose) $ putStrLn ("extendPathEnv: opt_path is "++ show opt_path)
when (verbAtLeast opts Verbose) $ putStrLn ("extendPathEnv: lib_dirs is "++ show lib_dirs)
when (verbAtLeast opts Verbose) $ putStrLn ("extendPathEnv: grm_path is "++ show grm_path)
ps <- liftM (nub . concat) $ mapM allSubdirs (nub paths)
mapM canonicalizePath ps mapM canonicalizePath ps
where where
allSubdirs :: FilePath -> IO [FilePath] allSubdirs :: FilePath -> IO [FilePath]
@@ -80,11 +85,15 @@ extendPathEnv opts = liftIO $ do
allSubdirs p = case last p of allSubdirs p = case last p of
'*' -> do let path = init p '*' -> do let path = init p
fs <- getSubdirs path fs <- getSubdirs path
return [path </> f | f <- fs] let starpaths = [path </> f | f <- fs]
when (verbAtLeast opts Verbose) $ putStrLn ("extendPathEnv: allSubdirs: * found "++show starpaths)
return starpaths
_ -> do exists <- doesDirectoryExist p _ -> do exists <- doesDirectoryExist p
if exists if exists
then return [p] then do
else do when (verbAtLeast opts Verbose) $ putStrLn ("ignore path "++p) when (verbAtLeast opts Verbose) $ putStrLn ("extendPathEnv: allSubdirs: found path "++show p)
return [p]
else do when (verbAtLeast opts Verbose) $ putStrLn ("extendPathEnv: allSubdirs: ignore path "++ show p)
return [] return []
getSubdirs :: FilePath -> IO [FilePath] getSubdirs :: FilePath -> IO [FilePath]